home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
The World of Computer Software.iso
/
yamp16.zip
/
VIRTGRAF.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-11
|
17KB
|
681 lines
/*
YAMP - Yet Another Matrix Program
Version: 1.6
Author: Mark Von Tress, Ph.D.
Date: 01/11/93
Copyright(c) Mark Von Tress 1993
Portions of this code are (c) 1991 by Allen I. Holub and are used by
permission
DISCLAIMER: THIS PROGRAM IS PROVIDED AS IS, WITHOUT ANY
WARRANTY, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
TO FITNESS FOR A PARTICULAR PURPOSE. THE AUTHOR DISCLAIMS
ALL LIABILITY FOR DIRECT OR CONSEQUENTIAL DAMAGES RESULTING
FROM USE OF THIS PROGRAM.
*/
#include "virt.h"
Axis::Axis(VMatrix &grf_vec, int col, int pixels, int pxlspplot)
{
Dispatch->Inclevel();
getlinesettings(&lineinfo);
valmin = 0;
step = 0;
ir = 0;
ifault = 0;
iv = 30;
maxpr = 6;
mpv = pxlspplot;
fmn = fmx = grf_vec.m(1, col);
double temp;
for (int i = 2; i <= grf_vec.r; i++) {
temp = grf_vec.m(i, col);
fmn = (temp < fmn) ? temp : fmn;
fmx = (temp > fmx) ? temp : fmx;
}
if (fmn == fmx) {
fmx = fmn + 0.5;
fmn = fmn - 0.5;
}
vals = new double[iv];
getvals(fmn, fmx, pixels, vals, &offset, &ifact, &nvals, &irprin);
Vals = new VMatrix;
*Vals = Fill(nvals, 1, 0);
for (i = 0; i < nvals; i++) {
double temp = (irprin != 0) ?
floor(0.5 + vals[i] *exp(((double) irprin) *log(10.0)))
*exp(- ((double) irprin) *log(10.0)) :
vals[i];
Vals->M(i + 1, 1) = temp;
}
Dispatch->Declevel();
}
Axis::~Axis(void)
{
delete vals;
delete Vals;
}
double Axis::dmax(double x, double y)
{
return ((x > y) ? x : y);
}
void Axis::scale(double fmn, double fmx, int n, int mpv,
double *valmin, double *step, int *nvals, int *ir, int *ifault)
{ double unit[13] = { 0, 12, 15, 20, 25, 30, 40, 50, 60, 80, 100, 120, 150};
double tol = 5.0e-6, bias = 1.0e-5, cover = 0.7, temp;
int i, j, minn = 2, maxn = 10000;
char buf[80] = { '\0' };
double fmax, fmin, finter, s, aj, tstep;
int nunit = 12;
fmax = fmx;
fmin = fmn;
*ifault = 0;
if (fmax < fmin) *ifault++;
if ((n < minn) || (n > maxn)) *ifault += 2;
if ((mpv <= 0) || (mpv >= n)) *ifault += 4;
if (*ifault) {
sprintf(buf, "SCALE: bad parameters in scale irprn = %d", *ifault);
closegraph();
Dispatch->Nrerror(buf);
}
*nvals = 1+ (n - 1) / mpv;
if ((fmax - fmin) <= (tol*((double) dmax(fabs(fmax), fabs(fmin))))){
*ifault = -1;
if (fmax < 0) fmax = 0;
if (fmax == 0) fmax = 1;
if (fmax > 0) fmin = 0;
}
finter =((double) n) / ((double) mpv);
s =(fmax - fmin) *(1.0+2.0*bias) / finter;
*ir = 0;
while (s <= 10.0) {
s *= 10;
(*ir)++;
}
while (s > 100) {
s /= 10;
(*ir)--;
}
i = 0;
while (s > unit[i]) i++;
LABEL1 :
*step = unit[i] *exp(- ((double) (*ir)) *log(10));
aj = 0;
LABEL2 :
do {
aj += 1.0;
} while ((unit[i] - 0.1) > (floor((unit[i] + 0.1) / aj) *aj));
tstep = (*step) / aj;
temp = fmin / tstep + aj*(0.5 / ((double) mpv) - finter*bias);
*valmin = floor(temp) *tstep;
if ((temp < 0) && (temp != floor(temp))) (*valmin) -= tstep;
if (fmax < ((*valmin) +(*step) *(finter*(1.0-bias) - 0.5 / ((double)mpv))))
goto LABEL3;
if ((unit[i] / unit[i + 1] *(1.0-1.0 / (aj*finter))) < cover) goto LABEL2;
i++;
if (i == nunit) printf("problem");
goto LABEL1;
LABEL3 :
for (j = 1; j <= 2; j++) {
aj *= 10;
if ((unit[i] - 0.1) < (floor((unit[i] + 0.1) / aj) *aj)) (*ir) -= 1;
}
} /* scale */
void Axis::axis(double valmin, double step, int nvals, int maxpr, int ir,
int *irprin, double *offset, int *ifact, double *vals, int iv,
int *ifault)
{
int irmax = 200, mprmax = 20;
double fmax, tmax, fl, fs, vstep, vmin, temp1 = 0, temp2 = 0;
double dtemp1 = 0, dtemp2 = 0;
int i, il, is, it, ilprin;
char buf[80] = { '\0' };
*ifault = 0;
if (nvals < 2) (*ifault)++;
fmax = valmin + step*((double) (nvals - 1));
if ((nvals >= 2) && (fmax <= valmin)) (*ifault) += 2;
if ((maxpr < 2) || (maxpr > mprmax)) (*ifault) += 4;
if (nvals > iv) (*ifault) += 8;
if (ir > irmax) (*ifault) += 16;
if (*ifault) {
sprintf(buf, "Axis: bad parameters in axis: error %d", *ifault);
closegraph();
Dispatch->Nrerror(buf);
}
tmax = exp(((double) maxpr) *log(10.0));
fl = fabs(fmax);
fs = fabs(valmin);
il = 0;
while (!((fl < 1.0) && (fs < 1.0))) {
fl /= 10;
fs /= 10;
il++;
}
while (!((fl >= 0.1) || (fs >= 0.1))) {
fl *= 10;
fs *= 10;
il -= 1;
}
is = il + ir;
it = is;
if ((valmin <= 0.0) && (fmax >= 0.0)) goto LABEL50;
LABEL40 :
fl = ((double) modf(fl, &dtemp1)) *10;
fs = ((double) modf(fs, &dtemp2)) *10;
if (it <= 0) {
closegraph();
Dispatch->Nrerror("Axis: error 16 in axis ");
}
if (((int) floor(fl)) != ((int) floor(fs))) goto LABEL50;
it--;
goto LABEL40;
LABEL50 :
*ifact = 0;
*offset = 0.0;
*irprin = (ir > 0) ? ir : 0;
ilprin = (il > 0) ? il : 0;
if (((*irprin) + ilprin) <= maxpr) goto LABEL70;
if (is <= maxpr) goto LABEL60;
*irprin = maxpr - 1;
*ifact = (it > maxpr) ? it : maxpr;
*ifact = (*ifact) - 1 - ir;
goto LABEL70;
LABEL60 :
*ifact = il - 1;
*irprin = is - 1;
LABEL70 :
fs = exp(- ((double) (*ifact)) *log(10.0));
vstep = step*fs;
vmin = valmin*fs;
if (!(is <= maxpr)) {
*offset = floor(vmin / 10.0) *10;
vmin -= (*offset);
}
for (i = 0; i < nvals; i++) {
vals[i] = vmin;
vmin += vstep;
}
fs = pow(0.1, ((double) (*irprin)));
temp1 = fabs(vals[0]) *fs + 0.5;
temp2 = fabs(vals[nvals - 1]) * fs + 0.5;
if ((temp1 < tmax) && (temp2 < tmax)) return;
il++;
is++;
it++;
goto LABEL50;
} /* end axis */
/* get scale and axis Applied Statistics algorithm 168 */
void Axis::getvals(double fmn, double fmx, int n, double *vals,
double *offset, int *ifact, int *nvals, int *irprin)
{
scale(fmn, fmx, n, mpv, &valmin, &step, nvals, &ir, &ifault);
axis(valmin, step, *nvals, maxpr, ir, irprin, offset, ifact,
vals, iv, &ifault);
//
// the following code fixes an axis where data is out of range
//
double st = Rescale(step);
double t = Rescale(fmn);
double trace;
int down = 0, up = 0;
if (t < vals[0])
for (trace = vals[0]; (t < trace) && (down + *nvals < iv);
down++, trace -= st);
t = Rescale(fmx);
if (t > vals[*nvals - 1])
for (trace = vals[*nvals - 1]; (t > trace) && (up + down + *nvals < iv);
up++, trace += st);
if (down + up + *nvals >= iv) {
// prevent a writeover past the end of vals
ifault = 8;
char buf[80] = { '\0' };
sprintf(buf, "Axis: bad parameters in axis: error %d", ifault);
closegraph();
Dispatch->Nrerror(buf);
}
t = vals[0] - ((double) down) *st;
for (int i = 0; i < down + up + *nvals; i++) {
vals[i] = t;
t += st;
}
*nvals += down + up;
}
strtype Axis::GetAxisLabel(strtype &name)
{
char xo[20] = { '\0' }, xi[20] = { '\0' };
char buf[80] = { '\0' };
strtype newname;
newname = name + " ";
gcvt(offset, 8, buf);
strcpy(xo, (const char *) buf);
gcvt(ifact, 8, buf);
strcpy(xi, (const char *) buf);
if (offset && ifact)
newname = newname + "((x+" + xo + ")*10**" + xi + ")";
if (!offset && ifact)
newname = newname + "(x*10**" + xi + ")";
if (offset && !ifact)
newname = newname + "(x+" + xo + ")";
return newname;
}
double Axis::Rescale(double x)
{
static double log10 = log(10.0);
double xo = x + offset;
double si = (xo <= 0.0) ? - 1.0 : 1.0;
double xv = (xo == 0.0) ? 0.0 :
si*exp(log(fabs(xo)) - ((double) ifact) *log10);
return xv;
}
//////////////////////// yaxis
YAxis::YAxis(VMatrix &grf, int xxlen, int yylen, int ww, int hh,
int bbmarg, int uumarg, int llmarg, int rrmarg) :
Axis(grf, 4, yylen, yylen / hh)
{
Dispatch->Inclevel();
h = hh;
w = ww;
bmarg = bbmarg;
umarg = uumarg;
lmarg = llmarg;
rmarg = rrmarg;
ylen = yylen;
xlen = xxlen;
maxy =(Mmax(*Vals)).m(3, 1);
miny =(Mmin(*Vals)).m(3, 1);
deltay =(fabs(maxy - miny) < 1.0e-10) ? 1.1*miny : maxy - miny;
deltay =((double) ylen) / deltay;
Dispatch->Cleanstack();
Dispatch->Declevel();
}
void YAxis::Show(boolean gridon)
{
// show yaxis
char *buf = new char[80];
strtype *junk = new strtype;
setviewport(lmarg, umarg, rmarg, bmarg, 1);
line(0, 0, 0, ylen + 1);
setviewport(0, umarg - h, lmarg, bmarg + h, 1);
settextjustify(RIGHT_TEXT, CENTER_TEXT);
int tickloc;
for (int i = 1; i <= nvals; i++) {
double temp = Vals->m(i, 1);
tickloc = ylen - (int) (deltay*(temp - miny)) + h;
gcvt(temp, (maxpr + 2), buf);
*junk = "";
*junk = *junk + buf + " ";
outtextxy(lmarg, tickloc, junk->StringAddress());
line(lmarg - w + 1, tickloc - 1, lmarg, tickloc - 1);
}
if (gridon) {
setviewport(lmarg, umarg - h, rmarg, bmarg + h, 1);
setlinestyle(lineinfo.linestyle, lineinfo.upattern, NORM_WIDTH);
for (int i = 1; i <= nvals; i++) {
double temp = Vals->m(i, 1);
tickloc = ylen - (int) (deltay*(temp - miny)) + h;
line(0, tickloc - 1, xlen, tickloc - 1);
}
setlinestyle(lineinfo.linestyle, lineinfo.upattern, THICK_WIDTH);
}
setviewport(lmarg, umarg, rmarg, bmarg, 1);
delete buf;
delete junk;
}
//////////// xaxis
XAxis::XAxis(VMatrix &grf, int xxlen, int yylen, int ww, int hh,
int bbmarg, int uumarg, int llmarg, int rrmarg) :
Axis(grf, 3, xxlen, xxlen / ww)
{
Dispatch->Inclevel();
xlen = xxlen;
ylen = yylen;
w = ww;
h = hh;
bmarg = bbmarg;
umarg = uumarg;
lmarg = llmarg;
rmarg = rrmarg;
maxx =(Mmax(*Vals)).m(3, 1);
minx =(Mmin(*Vals)).m(3, 1);
deltax =(fabs(maxx - minx) < 1.0e-10) ? 1.1*minx : maxx - minx;
deltax =((double) xlen) / deltax;
Dispatch->Cleanstack();
Dispatch->Declevel();
}
void XAxis::Show(boolean gridon)
{
char *buf = new char[80];
setviewport(lmarg, umarg, rmarg, bmarg, 1);
line(0, ylen, xlen, ylen);
int mdelta = w*(maxpr + 2) / 2 + w;
setviewport(lmarg - mdelta, bmarg, rmarg + mdelta, bmarg + 5*h, 1);
settextjustify(CENTER_TEXT, TOP_TEXT);
int tickloc;
for (int i = 1; i <= nvals; i++) {
double temp = Vals->m(i, 1);
tickloc = mdelta + (int) (deltax*(temp - minx));
gcvt(temp, (maxpr + 2), buf);
outtextxy(tickloc, h, buf);
line(tickloc + 1, 0, tickloc + 1, h / 2);
}
if (gridon) {
setviewport(lmarg - mdelta, umarg, rmarg + mdelta, bmarg, 1);
setlinestyle(lineinfo.linestyle, lineinfo.upattern, NORM_WIDTH);
for (int i = 1; i <= nvals; i++) {
double temp = Vals->m(i, 1);
tickloc = mdelta + (int) (deltax*(temp - minx));
line(tickloc + 1, 0, tickloc + 1, ylen);
}
setlinestyle(lineinfo.linestyle, lineinfo.upattern, THICK_WIDTH);
}
setviewport(lmarg, umarg, rmarg, bmarg, 1);
delete buf;
}
/////////////////////////////// graph matrix class
GMatrix::GMatrix(void)
{
title = new strtype;
title2 = new strtype;
xname = new strtype;
yname = new strtype;
PathToDriver = new strtype;
hrefs = new double[20];
vrefs = new double[20];
graphnum = 0;
nhrefs = nvrefs = -1;
RectangleOn = TTRUE;
XGridOn = YGridOn = FFALSE;
grf = new VMatrix("graph", 1, 4);
}
GMatrix::GMatrix(VMatrix &ROp, int symbol)
{
Dispatch->Inclevel();
nvrefs = nhrefs = -1;
title = new strtype;
*title = ROp.Getname(ROp);
title2 = new strtype;
xname = new strtype;
yname = new strtype;
PathToDriver = new strtype;
hrefs = new double[20];
vrefs = new double[20];
graphnum = 1;
RectangleOn = TTRUE;
XGridOn = YGridOn = FFALSE;
grf = new VMatrix("graph", 1, 4);
int n = ROp.r;
printf("\nMaking a Graph\n");
*grf =
Ch(Fill(n, 1, (double) graphnum), Ch(Fill(n, 1, (double) symbol), ROp));
Dispatch->Declevel();
}
GMatrix::~GMatrix(void)
{
delete grf;
delete title;
delete title2;
delete xname;
delete yname;
delete PathToDriver;
delete hrefs;
delete vrefs;
}
void GMatrix::Href(double href)
{
hrefs[++ nhrefs % 20] = href;
}
void GMatrix::Vref(double vref)
{
vrefs[++ nvrefs % 20] = vref;
}
void GMatrix::AddVec(VMatrix &ROp, int symbol)
{
Dispatch->Inclevel();
VMatrix *temp = new VMatrix;
graphnum++;
int n = ROp.r;
printf("\nAppending a new graph\n");
*temp =
Ch(Fill(n, 1, (double) graphnum), Ch(Fill(n, 1, (double) symbol), ROp));
*grf = Cv(*grf, *temp);
delete temp;
Dispatch->Declevel();
}
int GMatrix::gprintf(int *xloc, int *yloc, char *fmt,...)
{
va_list argptr; // Argument list pointer
char str[140]; // Buffer to build sting into
int cnt; // Result of SPRINTF for return
va_start(argptr, fmt); // Initialize va_ functions
cnt = vsprintf(str, fmt, argptr); // prints string to buffer
outtextxy(*xloc, *yloc, str); // Send string in graphics mode
*yloc += textheight("H") + 2; // Advance to next line
va_end(argptr); // Close va_ functions
return (cnt); // Return the conversion count
}
void GMatrix::Pause(void)
{
static char msg[] = "Esc aborts or press a key...";
int c;
c = getch();
if (0x1b == c) {
closegraph();
exit(1);
}
if (0 == c) {
c = getch();
}
cleardevice();
restorecrtmode();
}
void GMatrix::plotpoint(int ix, int iy, int symbol)
{
char str[2] = { (char) symbol, '\0' };
outtextxy(ix, iy, str);
}
void GMatrix::Show(void)
{
Dispatch->Inclevel();
GraphDriver = DETECT;
// GraphDriver = CGA;
// GraphMode = CGAHI;
initgraph(&GraphDriver, &GraphMode, PathToDriver->StringAddress());
ErrorCode = graphresult();
if (ErrorCode != grOk) {
printf(" Graphics System Error: %s\n", grapherrormsg(ErrorCode));
exit(1);
}
cleardevice();
MaxX = getmaxx();
MaxY = getmaxy(); // Read size of screen
getviewsettings(&viewinfo);
getlinesettings(&lineinfo);
setcolor(MaxColors - 1);
MaxColors = getmaxcolor() + 1;
setcolor(MaxColors - 1);
//Black on white for screen captures for EGA/VGA
if (GraphDriver == VGA || GraphDriver == EGA ){
setbkcolor(WHITE);
setpalette(1,BLACK);
setcolor( 1 );
}
setviewport(0, 0, MaxX, MaxY, 1);
settextjustify(CENTER_TEXT, CENTER_TEXT);
int x = MaxX / 2, y = 4;
gprintf(&x, &y, title->StringAddress());
gprintf(&x, &y, title2->StringAddress());
int h = textheight("H");
int w = textwidth("Z");
int lmarg = 10*w, rmarg = MaxX - 10 * w, umarg = 5*h, bmarg = MaxY - 5*h;
setviewport(lmarg, umarg - 1, rmarg, bmarg, 1);
getviewsettings(&viewinfo);
int xlen = viewinfo.right - viewinfo.left;
int ylen = viewinfo.bottom - viewinfo.top;
setlinestyle(lineinfo.linestyle, lineinfo.upattern, THICK_WIDTH);
if (RectangleOn) rectangle(0, 0, xlen, ylen);
///////////// draw axies
YAxis *yaxis = new YAxis(*grf, xlen, ylen, w, h, bmarg, umarg, lmarg, rmarg);
yaxis->Show(YGridOn);
XAxis *xaxis = new XAxis(*grf, xlen, ylen, w, h, bmarg, umarg, lmarg, rmarg);
xaxis->Show(XGridOn);
////////////// plot points
setlinestyle(lineinfo.linestyle, lineinfo.upattern, NORM_WIDTH);
setviewport(lmarg, umarg, rmarg, bmarg, 1);
settextjustify(CENTER_TEXT, CENTER_TEXT);
int lx, ly, ix, iy, cnter = 1;
boolean newgraph = TTRUE;
double deltax = ((double) xlen) / (xaxis->maxx - xaxis->minx);
double deltay = ((double) ylen) / (yaxis->maxy - yaxis->miny);
for (int i = 1; i <= grf-> r; i++) {
if (cnter != ((int) grf->m(i, 1))) {
cnter++;
newgraph = TTRUE;
}
double symbol = grf->m(i, 2);
double tempx = xaxis->Rescale(grf->m(i, 3));
double tempy = yaxis->Rescale(grf->m(i, 4));
ix = (int) ((tempx - xaxis->minx) *deltax);
iy = ylen - (int) ((tempy - yaxis->miny) *deltay);
plotpoint(ix, iy, abs(symbol));
if (symbol <= 0.0) {
if (!newgraph) line(lx, ly, ix, iy);
newgraph = FFALSE;
}
lx = ix;
ly = iy;
}
if (nhrefs > - 1) {
int indx = (nhrefs > 19) ? 19 : nhrefs;
for (i = 0; i <= indx; i++) {
double temph = yaxis->Rescale(hrefs[i]);
iy = ylen -((int) ((temph - yaxis->miny) *deltay));
line(0, iy, xlen, iy);
}
}
if (nvrefs > - 1) {
int indx = (nvrefs > 19) ? 19 : nvrefs;
for (i = 0; i <= indx; i++) {
double tempv = xaxis->Rescale(vrefs[i]);
ix = (int) ((tempv - xaxis->minx) *deltax);
line(ix, 0, ix, ylen);
}
}
/////////// display axis labels
setviewport(0, 0, MaxX, MaxY, 1);
strtype *ylabel = new strtype;
*ylabel = yaxis->GetAxisLabel(*yname);
x = lmarg;
y = umarg - h - 3;
gprintf(&x, &y, ylabel->StringAddress());
strtype *xlabel = new strtype;
*xlabel = xaxis->GetAxisLabel(*xname);
y = bmarg + 3*h + h / 2 + 2;
x = MaxX / 2;
gprintf(&x, &y, xlabel->StringAddress());
Pause();
delete xaxis;
delete yaxis;
delete xlabel;
delete ylabel;
Dispatch->Cleanstack();
Dispatch->Declevel();
}